package com.adv.ems.db.utils;

import cn.hutool.core.io.FileUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.util.StringUtils;

import java.io.File;
import java.util.List;
import java.util.Map;

public class DbClassAutoCreate {
    public static final String baseFilePath = "D:\\eclipse-workspace\\advance-ems-server\\src\\main\\java";
    public static final String mapperPath = "com.adv.ems.db.mapper";
    public static final String entityPath = "com.adv.ems.db.entity";
    public static final String entity_prefix_replace_path = "t_";
    public static final String entity_after_path = "DO";
    public static final String managerPath = "com.adv.ems.manager";

    public static void createMapper(String tableName, Boolean force) {
        String mapperClassName = getBaseClassName(tableName) + "Mapper";
        String entityClassName = getBaseClassName(tableName) + entity_after_path;
        StringBuilder sb = new StringBuilder();
        String s1 = "package %s;\n" +
                "\n" +
                "import com.baomidou.mybatisplus.core.mapper.BaseMapper;\n" +
                "import %s.%s;\n" +
                "\n" +
                "public interface %s extends BaseMapper<%s> {}";
        sb.append(String.format(s1, mapperPath, entityPath, entityClassName, mapperClassName, entityClassName));
        String content = sb.toString();
        String savePath = baseFilePath + File.separator + mapperPath.replaceAll("[\\.]", "/") + File.separator + mapperClassName + ".java";
        File file = new File(savePath);
        if (file.exists() && !force) {
            return;
        }
        FileUtil.writeString(content, file, "utf-8");
    }

    public static void createMapperXml(String tableName, Boolean force) {
        String mapperClassName = getBaseClassName(tableName) + "Mapper";
        StringBuilder sb = new StringBuilder();
        String s1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<!DOCTYPE mapper\n" +
                "        PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n" +
                "        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n" +
                "<mapper namespace=\"%s\"></mapper>\n";
        sb.append(String.format(s1, mapperPath + "." + mapperClassName));
        String content = sb.toString();
        String savePath = baseFilePath + File.separator + ".." + File.separator + "resources/mapper/" + mapperClassName + ".xml";
        File file = new File(savePath);
        if (file.exists() && !force) {
            return;
        }
        FileUtil.writeString(content, file, "utf-8");
    }

    public static void createEntity(Map.Entry<String, List<DbUtil.ColumnInfo>> tableInfo, Boolean force) {
        String tableName = tableInfo.getKey();
        String className = getBaseClassName(tableName) + entity_after_path;
        StringBuilder sb = new StringBuilder();
        String s1 = "package %s;\n" +
                "\n" +
                "import com.baomidou.mybatisplus.annotation.IdType;\n" +
                "import com.baomidou.mybatisplus.annotation.TableId;\n" +
                "import com.baomidou.mybatisplus.annotation.TableField;\n" +
                "import com.baomidou.mybatisplus.annotation.TableName;\n" +
                "import lombok.Data;\n" +
                "import lombok.EqualsAndHashCode;\n" +
                "\n" +
                "@Data\n" +
                "@EqualsAndHashCode(callSuper = true)\n" +
                "@TableName(\"`%s`\")\n" +
                "public class %s extends BaseDO{\n";
        sb.append(String.format(s1, entityPath, tableInfo.getKey(), className));
        Boolean hasPrimaryKey = false;
        for (DbUtil.ColumnInfo column : tableInfo.getValue()) {
            FieldProperty property = getFieldName(column);
            if (property.isPrimaryKey && !hasPrimaryKey) {
                hasPrimaryKey = true;
                sb.append(String.format("    @%s(value = \"`%s`\"%s)\n", "TableId", column.getColumnName(), ", type = IdType.AUTO"));
            }else {
                sb.append(String.format("    @%s(value = \"`%s`\"%s)\n", "TableField", column.getColumnName(), ""));
            }
            sb.append(String.format("    private %s %s;\n", property.javaType.getName(), property.fieldName));
        }
        sb.append("}");
        String content = sb.toString();
        String savePath = baseFilePath + File.separator + entityPath.replaceAll("[\\.]", "/") + File.separator + className + ".java";
        File file = new File(savePath);
        if (file.exists() && !force) {
            return;
        }
        FileUtil.writeString(content, file, "utf-8");
    }

    public static void createManager(String tableName, Boolean force) {
        String mapperClassName = getBaseClassName(tableName) + "Mapper";
        String entityClassName = getBaseClassName(tableName) + entity_after_path;
        String className = getBaseClassName(tableName);
        String interfaceName = getBaseClassName(tableName) + "Manager";
        String implName = getBaseClassName(tableName) + "ManagerImpl";

        String i = String.format("package %s;\n" +
                "\n" +
                "public interface %s {}", managerPath, interfaceName);
        String savePath = baseFilePath + File.separator + managerPath.replaceAll("[\\.]", "/") + File.separator + interfaceName + ".java";
        File file = new File(savePath);
        if (file.exists() && !force) {
            return;
        }
        FileUtil.writeString(i, file, "utf-8");

        String im = String.format("package %s.impl;\n" +
                "\n" +
                "import %s.%s;\n" +
                "import %s.%s;\n" +
                "import %s.%s;\n" +
                "import org.springframework.stereotype.Service;\n" +
                "\n" +
                "@Service\n" +
                "public class %s extends BaseManagerImpl<%s, %s> implements %sManager {}",
                managerPath, mapperPath, mapperClassName, entityPath, entityClassName, managerPath, interfaceName, implName, mapperClassName, entityClassName, className);

        savePath = baseFilePath + File.separator + managerPath.replaceAll("[\\.]", "/") + File.separator + "impl" + File.separator + implName + ".java";
        file = new File(savePath);
        if (file.exists() && !force) {
            return;
        }
        FileUtil.writeString(im, file, "utf-8");
    }

    public static String getBaseClassName(String tableName) {
        String s = tableName.replaceFirst(entity_prefix_replace_path, "");
        StringBuilder sb = new StringBuilder();
        String[] arr = s.split("_");
        for (String ss : arr) {
            if (!StringUtils.hasLength(ss)) {
                continue;
            }
            sb.append(ss.substring(0, 1).toUpperCase());
            sb.append(ss.substring(1));
        }
        return sb.toString();
    }

    public static FieldProperty getFieldName(DbUtil.ColumnInfo column) {
        StringBuilder sb = new StringBuilder();
        String[] arr = column.getColumnName().split("_");
        for (int i = 0; i < arr.length; i++) {
            String ss = arr[i];
            if (!StringUtils.hasLength(ss)) {
                continue;
            }
            if (i == 0) {
                sb.append(ss);
            }else {
                sb.append(ss.substring(0, 1).toUpperCase());
                sb.append(ss.substring(1));
            }
        }
        return new FieldProperty(sb.toString(), column.getJavaType(), column.getIsPrimaryKey());
    }

    @Data
    @AllArgsConstructor
    public static class FieldProperty {
        private String fieldName;
        private Class javaType;
        private Boolean isPrimaryKey;

    }

    public static void main(String[] args) {
        Map<String, List<DbUtil.ColumnInfo>> stringListMap = DbUtil.readInfo("127.0.0.1", "3306", "root", "123456", "advance_ems");
        for (Map.Entry<String, List<DbUtil.ColumnInfo>> entry : stringListMap.entrySet()) {
            createMapper(entry.getKey(), false);
            createMapperXml(entry.getKey(), false);
            createEntity(entry, true);
            createManager(entry.getKey(), false);
        }
    }
}
